package com.qumitech.visualnovel.service.script.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qumitech.visualnovel.component.cache.RedisCache;
import com.qumitech.visualnovel.component.util.BeanFactoryUtil;
import com.qumitech.visualnovel.component.util.CommonUtil;
import com.qumitech.visualnovel.component.util.DateUtil;
import com.qumitech.visualnovel.component.util.TimeUtils;
import com.qumitech.visualnovel.controller.vo.statics.AccountPayStaticsVO;
import com.qumitech.visualnovel.datasource.app.AccountMapper;
import com.qumitech.visualnovel.datasource.app.ShopOrderDOMapper;
import com.qumitech.visualnovel.datasource.console.AccountLoginMapper;
import com.qumitech.visualnovel.datasource.console.BookReadInfoDAOMapper;
import com.qumitech.visualnovel.datasource.console.view.*;
import com.qumitech.visualnovel.datasource.editor.BookDAOMapper;
import com.qumitech.visualnovel.model.dao.app.ShopOrderDO;
import com.qumitech.visualnovel.model.dao.console.BookReadInfoDAO;
import com.qumitech.visualnovel.model.dao.console.view.*;
import com.qumitech.visualnovel.model.dao.editor.BookDAO;
import com.qumitech.visualnovel.model.dto.BookStatisticQueryDTO;
import com.qumitech.visualnovel.model.dto.script.EventIdEnum;
import com.qumitech.visualnovel.model.dto.script.UserBehaviorDTO;
import com.qumitech.visualnovel.service.script.ScriptService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

@Slf4j
@Service("scriptServiceImpl")
public class ScriptServiceImpl implements ScriptService {
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private AccountLoginMapper accountLoginMapper;
    @Autowired
    private ShopOrderDOMapper shopOrderDOMapper;
    @Autowired
    private BookReadInfoDAOMapper bookReadInfoDAOMapper;
    @Autowired
    private PayStaticsViewDOMapper payStaticsViewDOMapper;
    @Autowired
    private PayTransferViewDOMapper payTransferViewDOMapper;
    @Autowired
    private BookTotalStaticsDOMapper bookTotalStaticsDOMapper;
    @Autowired
    private BookChapterStaticsDOMapper bookChapterStaticsDOMapper;
    @Autowired
    private BookOptionStaticsDOMapper bookOptionStaticsDOMapper;
    @Autowired
    private BookDAOMapper bookDAOMapper;

    @Autowired
    private RedisCache redisCache;


    @Transactional
    @Override
    public void start(Date startTime, Date endTime) {
        Date dayStart = startTime;
        while (dayStart.before(endTime)) {
            Date dayEnd = DateUtils.addDays(dayStart, 1);
            ScriptService scriptService = (ScriptService) (BeanFactoryUtil.getBean("scriptServiceImpl"));
            scriptService.processOneDay(dayStart, dayEnd);
            dayStart = dayEnd;
        }
    }

    @Transactional
    public void processOneDay(Date dayStart, Date dayEnd) {
        // 充值统计
        processPayStatics(dayStart, dayEnd);

        // 充值转化
        processPayTransfer(dayStart, dayEnd);

        // 书籍总体数据
        processBookTotal(dayStart, dayEnd);

        log.info("finish processOneDay");
    }


    public void processPayStatics(Date dayStart, Date dayEnd) {
        // 插入注册人数
        List<AccountPayStaticsVO> registerStatics = accountMapper.countRegister(dayStart, dayEnd);
        registerStatics.forEach(staticsVO -> {
            PayStaticsViewDO viewDO = new PayStaticsViewDO();
            viewDO.setDay(dayStart);
            viewDO.setChannel(staticsVO.getChannel());
            viewDO.setGeoName(staticsVO.getGeoName());
            viewDO.setRegisterNum(staticsVO.getRegisterNum());
            payStaticsViewDOMapper.insertSelective(viewDO);
        });

        // 插入或更新活跃人数
        String tableName = CommonUtil.getTableName(TimeUtils.formatDate(dayStart), "account_login");
        log.info("processPayStatics,tableName={}", tableName);
//        List<AccountPayStaticsVO> activeStatics = accountLoginMapper.countActive()
        List<AccountPayStaticsVO> activeStatics = accountLoginMapper.countActive(tableName, dayStart, dayEnd);
        activeStatics.forEach(staticsVO -> {
            PayStaticsViewDO viewDO = new PayStaticsViewDO();
            viewDO.setDay(dayStart);
            viewDO.setChannel(staticsVO.getChannel());
            viewDO.setGeoName("未统计");
            viewDO.setActiveNum(staticsVO.getActiveNum());
            payStaticsViewDOMapper.insertSelective(viewDO);
        });

        // 插入或更新订单人数
        List<AccountPayStaticsVO> orderStatics = shopOrderDOMapper.countPayOrder(dayStart, dayEnd);

        orderStatics.forEach(orderVO -> {
            PayStaticsViewDOExample example = new PayStaticsViewDOExample();
            example.createCriteria().andDayEqualTo(dayStart).andChannelEqualTo(orderVO.getChannel())
                    .andGeoNameEqualTo(orderVO.getGeoName());
            List<PayStaticsViewDO> list = payStaticsViewDOMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(list)) {
                PayStaticsViewDO viewDO = new PayStaticsViewDO();
                viewDO.setDay(dayStart);
                viewDO.setChannel(orderVO.getChannel());
                viewDO.setGeoName(orderVO.getGeoName());
                viewDO.setPayNum(orderVO.getPayNum());
                viewDO.setPayAccountNum(orderVO.getPayAccountNum());
                viewDO.setPayAmount(orderVO.getPayAmount());
                payStaticsViewDOMapper.insertSelective(viewDO);
            } else {
                PayStaticsViewDO viewDO = list.get(0);
                viewDO.setPayNum(orderVO.getPayNum());
                viewDO.setPayAccountNum(orderVO.getPayAccountNum());
                viewDO.setPayAmount(orderVO.getPayAmount());
                payStaticsViewDOMapper.updateByPrimaryKeySelective(viewDO);
            }
        });

    }

    public void processPayTransfer(Date dayStart, Date dayEnd) {
        List<AccountPayStaticsVO> orderStatics = shopOrderDOMapper.countPayOrder(dayStart, dayEnd);
        orderStatics.forEach(orderVO -> {
            PayTransferViewDO viewDO = new PayTransferViewDO();
            viewDO.setDay(dayStart);
            viewDO.setChannel(orderVO.getChannel());
            viewDO.setGeoName(orderVO.getGeoName());
            viewDO.setPayNum(orderVO.getPayNum());
            viewDO.setPayAccountNum(orderVO.getPayAccountNum());
            viewDO.setPayAmount(orderVO.getPayAmount());
            payTransferViewDOMapper.insertSelective(viewDO);
        });

    }


    public void processBookTotal(Date dayStart, Date dayEnd) {
        BookStatisticQueryDTO queryDTO = new BookStatisticQueryDTO();
        queryDTO.setStartTime(TimeUtils.formatDate(dayStart));
        queryDTO.setEndTime(TimeUtils.formatDate(dayEnd));
        List<BookReadInfoDAO> list = bookReadInfoDAOMapper.list(queryDTO);
        for (BookReadInfoDAO readInfo : list) {
            BookTotalStaticsDO staticsDO = new BookTotalStaticsDO();
            staticsDO.setDay(readInfo.getDtdate());
            staticsDO.setChannel("未统计");
            staticsDO.setGeoName("未统计");
            staticsDO.setBookId(readInfo.getBookId().intValue());
            staticsDO.setBookTitle(bookDAOMapper.selectByPrimaryKey(readInfo.getBookId()).getTitle());
            staticsDO.setReadNum(readInfo.getSumReaders());
            staticsDO.setFirstChapterFinishNum(readInfo.getCpt1Readers());
            staticsDO.setChapterUnlockNum(readInfo.getChapterUnlockTimes());
            staticsDO.setChapterUnlockCost(readInfo.getChapterUnlockKeys());
            staticsDO.setOptionUnlockNum(readInfo.getOptionUnlockTimes());
            staticsDO.setOptionUnlockCost(readInfo.getOptionUnlockDiamonds());
            bookTotalStaticsDOMapper.insertSelective(staticsDO);
        }

    }


    @Override
    public void processLogOneDay(String day) {
        String path = String.format("/data/console/logs/userBehavior/%s", day);
        Iterator<File> iterator = FileUtils.iterateFiles(new File(path), new String[]{"txt"}, false);
        while (iterator.hasNext()) {
            File file = iterator.next();
            ScriptService scriptService = (ScriptService) (BeanFactoryUtil.getBean("scriptServiceImpl"));
            scriptService.processOneFile(file);
        }
    }

    @Transactional
    public void processOneFile(File file) {
        log.info("start,processOneFile,file={}", file.getAbsolutePath());
        List<String> lines = null;
        try {
            lines = FileUtils.readLines(file);
        } catch (IOException e) {
            log.info("processLogOneDay,readLines,error,fileName={}", file.getAbsolutePath());
            return;
        }
        for (String line : lines) {
            try {
                UserBehaviorDTO userBehaviorDTO = JSON.toJavaObject(JSON.parseObject(line), UserBehaviorDTO.class);
                processPayStatics(userBehaviorDTO);
                processPayTransfer(userBehaviorDTO);
                processBookTotal(userBehaviorDTO);
                processBookChapter(userBehaviorDTO);
                processBookOption(userBehaviorDTO);
            } catch (Exception e) {
                log.info("processOneFile One Line,exception={}", e.getMessage());
            }
        }
    }


    private void processPayStatics(UserBehaviorDTO userBehaviorDTO) {
        log.info("start,processPayStatics,eventId={}", userBehaviorDTO.getEventId());
        if (EventIdEnum.mustFind(userBehaviorDTO.getEventId()) != EventIdEnum.RECHARGE_CLICK_SELECT) {
            return;
        }

        // init
        String day = userBehaviorDTO.getEventTime().split(" ")[0];
        PayStaticsViewDOExample example = new PayStaticsViewDOExample();
        Date dayDate = TimeUtils.parse(day, "yyyy-MM-dd");
        example.createCriteria().andDayEqualTo(dayDate)
                .andChannelEqualTo(userBehaviorDTO.getAppChannel()).andGeoNameEqualTo(userBehaviorDTO.getGeoName());
        List<PayStaticsViewDO> viewDOS = payStaticsViewDOMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(viewDOS)) {
            PayStaticsViewDO viewDO = new PayStaticsViewDO();
            viewDO.setDay(dayDate);
            viewDO.setChannel(userBehaviorDTO.getAppChannel());
            viewDO.setGeoName(userBehaviorDTO.getGeoName());
            payStaticsViewDOMapper.insertSelective(viewDO);
        }

        // 插入或更新订单人数
        Date dayStart = dayDate;
        Date dayEnd = DateUtils.addDays(dayStart, 1);
        List<AccountPayStaticsVO> orderStatics = shopOrderDOMapper.countPayOrder(dayStart, dayEnd);
        orderStatics.forEach(orderVO -> {
            PayStaticsViewDOExample viewDOExample = new PayStaticsViewDOExample();
            viewDOExample.createCriteria().andDayEqualTo(dayStart).andChannelEqualTo(orderVO.getChannel())
                    .andGeoNameEqualTo(orderVO.getGeoName());
            List<PayStaticsViewDO> list = payStaticsViewDOMapper.selectByExample(viewDOExample);
            if (CollectionUtils.isEmpty(list)) {
                PayStaticsViewDO viewDO = new PayStaticsViewDO();
                viewDO.setDay(dayStart);
                viewDO.setChannel(orderVO.getChannel());
                viewDO.setGeoName(orderVO.getGeoName());
                viewDO.setPayNum(orderVO.getPayNum());
                viewDO.setPayAccountNum(orderVO.getPayAccountNum());
                viewDO.setPayAmount(orderVO.getPayAmount());
                payStaticsViewDOMapper.insertSelective(viewDO);
            } else {
                PayStaticsViewDO viewDO = list.get(0);
                viewDO.setPayNum(orderVO.getPayNum());
                viewDO.setPayAccountNum(orderVO.getPayAccountNum());
                viewDO.setPayAmount(orderVO.getPayAmount());
                payStaticsViewDOMapper.updateByPrimaryKeySelective(viewDO);
            }
        });

        // update
        PayStaticsViewDO viewDO = payStaticsViewDOMapper.selectByExample(example).get(0);
        viewDO.setOrderNum(viewDO.getOrderNum() + 1);
        String redisKey = getRedisPayKey(day);
        if (!redisCache.sIsMember(redisKey, userBehaviorDTO.getUid())) {
            redisCache.sadd(redisKey, userBehaviorDTO.getUid());
            viewDO.setOrderAccountNum(viewDO.getOrderAccountNum() + 1);
        }
        payStaticsViewDOMapper.updateByPrimaryKeySelective(viewDO);
    }

    private String getRedisPayKey(String day) {
        return String.format("pay-statics-%s", day);
    }

    private void processPayTransfer(UserBehaviorDTO userBehaviorDTO) {
        log.info("start,processPayTransfer,eventId={}", userBehaviorDTO.getEventId());
        EventIdEnum idEnum = EventIdEnum.mustFind(userBehaviorDTO.getEventId());
        if (idEnum == null || !idEnum.ifProcessPayTransfer()) {
            return;
        }
        JSONObject jsonObject = JSON.parseObject(userBehaviorDTO.getEventData());
        if (jsonObject == null || StringUtils.isEmpty(jsonObject.getString("book_id"))) {
            return;
        }
        Integer bookId = Integer.parseInt(jsonObject.getString("book_id"));
        // init
        String day = userBehaviorDTO.getEventTime().split(" ")[0];
        PayTransferViewDOExample example = new PayTransferViewDOExample();
        Date dayDate = TimeUtils.parse(day, "yyyy-MM-dd");
        example.createCriteria().andDayEqualTo(dayDate).andChannelEqualTo(userBehaviorDTO.getAppChannel())
                .andGeoNameEqualTo(userBehaviorDTO.getGeoName()).andBookIdEqualTo(bookId);
        List<PayTransferViewDO> viewDOS = payTransferViewDOMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(viewDOS)) {
            PayTransferViewDO viewDO = new PayTransferViewDO();
            viewDO.setDay(dayDate);
            viewDO.setChannel(userBehaviorDTO.getAppChannel());
            viewDO.setGeoName(userBehaviorDTO.getGeoName());
            viewDO.setBookId(bookId);
            viewDO.setBookTitle(bookDAOMapper.selectByPrimaryKey((long) bookId).getTitle());
            payTransferViewDOMapper.insertSelective(viewDO);
        }

        PayTransferViewDO viewDO = payTransferViewDOMapper.selectByExample(example).get(0);
        if (idEnum == EventIdEnum.READ_CLICK_STORY) {
            String key = getRedisBookReadKey(day, viewDO.getBookId(), "read");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                viewDO.setReadAccountNum(viewDO.getReadAccountNum() + 1);
            }
        }

        if (idEnum == EventIdEnum.RECHARGE_VIEW_POP) {
            String key = getRedisBookReadKey(day, viewDO.getBookId(), "pay-pop");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                viewDO.setPayHintAccountNum(viewDO.getPayHintAccountNum() + 1);
            }
        }

        if (idEnum == EventIdEnum.RECHARGE_CLICK_SELECT) {
            String key = getRedisBookReadKey(day, viewDO.getBookId(), "create-order");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                viewDO.setOrderAccountNum(viewDO.getOrderAccountNum() + 1);
            }
            viewDO.setOrderNum(viewDO.getOrderNum() + 1);
        }

        if (idEnum == EventIdEnum.RECHARGE_SUCC) {
            String key = getRedisBookReadKey(day, viewDO.getBookId(), "recharge-succ");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                viewDO.setPayAccountNum(viewDO.getPayAccountNum() + 1);
            }
            viewDO.setPayNum(viewDO.getPayNum() + 1);
            ShopOrderDO shopOrderDO = shopOrderDOMapper.selectByOid(jsonObject.getString("oid"));
            viewDO.setPayAmount(viewDO.getPayAmount() + shopOrderDO.getPrice());
        }
        payTransferViewDOMapper.updateByPrimaryKeySelective(viewDO);
    }

    private String getRedisBookReadKey(String day, Integer bookId, String type) {
        return String.format("book-read-%s-%s-%s", day, type, bookId);
    }

    private void processBookTotal(UserBehaviorDTO userBehaviorDTO) {
        log.info("start,processBookTotal,eventId={}", userBehaviorDTO.getEventId());
        EventIdEnum idEnum = EventIdEnum.mustFind(userBehaviorDTO.getEventId());
        if (idEnum == null || !idEnum.ifProcessBookTotal()) {
            return;
        }
        JSONObject jsonObject = JSON.parseObject(userBehaviorDTO.getEventData());
        if (jsonObject == null || StringUtils.isEmpty(jsonObject.getString("book_id"))) {
            return;
        }
        Integer bookId = Integer.parseInt(jsonObject.getString("book_id"));
        // init
        String day = userBehaviorDTO.getEventTime().split(" ")[0];
        BookTotalStaticsDOExample example = new BookTotalStaticsDOExample();
        Date dayDate = TimeUtils.parse(day, "yyyy-MM-dd");
        example.createCriteria().andDayEqualTo(dayDate).andChannelEqualTo(userBehaviorDTO.getAppChannel())
                .andGeoNameEqualTo(userBehaviorDTO.getGeoName()).andBookIdEqualTo(bookId);
        List<BookTotalStaticsDO> viewDOS = bookTotalStaticsDOMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(viewDOS)) {
            BookTotalStaticsDO staticsDO = new BookTotalStaticsDO();
            staticsDO.setDay(dayDate);
            staticsDO.setChannel(userBehaviorDTO.getAppChannel());
            staticsDO.setGeoName(userBehaviorDTO.getGeoName());
            staticsDO.setBookId(bookId);
            BookDAO bookDAO = bookDAOMapper.selectByPrimaryKey((long) bookId);
            staticsDO.setBookTitle(bookDAO.getTitle());
            bookTotalStaticsDOMapper.insertSelective(staticsDO);
        }

        BookTotalStaticsDO staticsDO = bookTotalStaticsDOMapper.selectByExample(example).get(0);
        if (idEnum == EventIdEnum.READ_CLICK_STORY) {
            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setReadAccountNum(staticsDO.getReadAccountNum() + 1);
            }
            staticsDO.setReadNum(staticsDO.getReadNum() + 1);
        }

        if (idEnum == EventIdEnum.READ_OTHER_FIRST) {
            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-first");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setFirstReadNum(staticsDO.getFirstReadNum() + 1);
            }
        }

        if (idEnum == EventIdEnum.READ_OTHER_FIRST_CHAPTER_FINISH) {
            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-first-chapter-finish");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setFirstChapterFinishNum(staticsDO.getFirstChapterFinishNum() + 1);
            }
        }

        if (idEnum == EventIdEnum.READ_OTHER_CHAPTER_UNLOCK) {
            staticsDO.setChapterUnlockNum(staticsDO.getChapterUnlockNum() + 1);
            int costNum = jsonObject.getInteger("cost_num");
            if (costNum > 0) {
                staticsDO.setChapterUnlockCost(staticsDO.getChapterUnlockCost() + costNum);
                String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-cost-chapter-unlock");
                if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                    staticsDO.setCostChapterUnlockNum(staticsDO.getCostChapterUnlockNum() + 1);
                }
            }
        }

        if (idEnum == EventIdEnum.READ_OTHER_OPTION_UNLOCK) {
            staticsDO.setOptionUnlockNum(staticsDO.getOptionUnlockNum() + 1);
            int costNum = jsonObject.getInteger("cost_num");
            if (costNum > 0) {
                staticsDO.setOptionUnlockCost(staticsDO.getOptionUnlockCost() + costNum);
                String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-cost-option-unlock");
                if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                    staticsDO.setCostOptionUnlockNum(staticsDO.getCostOptionUnlockNum() + 1);
                }
            }
        }

        if (idEnum == EventIdEnum.BOOK_OTHER_LIKE) {
            staticsDO.setBookLikeNum(staticsDO.getBookLikeNum() + 1);
        }
        if (idEnum == EventIdEnum.BOOK_OTHER_COMMENT) {
            staticsDO.setBookCommentNum(staticsDO.getBookCommentNum() + 1);
        }

        bookTotalStaticsDOMapper.updateByPrimaryKeySelective(staticsDO);
    }


    private void processBookChapter(UserBehaviorDTO userBehaviorDTO) {
        log.info("start,processBookChapter,eventId={}", userBehaviorDTO.getEventId());
        EventIdEnum idEnum = EventIdEnum.mustFind(userBehaviorDTO.getEventId());
        if (idEnum == null || !idEnum.ifProcessBookChapter()) {
            return;
        }
        JSONObject jsonObject = JSON.parseObject(userBehaviorDTO.getEventData());

        Integer bookId = Integer.parseInt(jsonObject.getString("book_id"));
        Integer chapterIndex = Integer.parseInt(jsonObject.getString("chapter_index"));
        // init
        String day = userBehaviorDTO.getEventTime().split(" ")[0];
        BookChapterStaticsDOExample example = new BookChapterStaticsDOExample();
        Date dayDate = TimeUtils.parse(day, "yyyy-MM-dd");
        example.createCriteria().andDayEqualTo(dayDate).andChannelEqualTo(userBehaviorDTO.getAppChannel())
                .andGeoNameEqualTo(userBehaviorDTO.getGeoName()).andBookIdEqualTo(bookId)
                .andChapterIndexEqualTo(chapterIndex);
        List<BookChapterStaticsDO> staticsDOS = bookChapterStaticsDOMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(staticsDOS)) {
            BookChapterStaticsDO staticsDO = new BookChapterStaticsDO();
            staticsDO.setDay(dayDate);
            staticsDO.setChannel(userBehaviorDTO.getAppChannel());
            staticsDO.setGeoName(userBehaviorDTO.getGeoName());
            staticsDO.setBookId(bookId);
            staticsDO.setBookTitle(bookDAOMapper.selectByPrimaryKey((long) bookId).getTitle());
            staticsDO.setChapterIndex(chapterIndex);
            bookChapterStaticsDOMapper.insertSelective(staticsDO);
        }

        BookChapterStaticsDO staticsDO = bookChapterStaticsDOMapper.selectByExample(example).get(0);
        if (idEnum == EventIdEnum.READ_VIEW_CHAPTER) {
            staticsDO.setReadNum(staticsDO.getReadNum() + 1);

            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-chapter");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setReadAccountNum(staticsDO.getReadAccountNum() + 1);
            }
        }

        if (idEnum == EventIdEnum.READ_VIEW_CHAPTER_FINISH) {
            staticsDO.setReadFinishNum(staticsDO.getReadFinishNum() + 1);

            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-chapter-finish");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setReadFinishAccountNum(staticsDO.getReadFinishAccountNum() + 1);
            }
        }


        if (idEnum == EventIdEnum.READ_OTHER_CHAPTER_UNLOCK) {
            staticsDO.setUnlockNum(staticsDO.getUnlockNum() + 1);

            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-chapter-unlock");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setUnlockAccountNum(staticsDO.getUnlockAccountNum() + 1);
            }

            int costNum = jsonObject.getInteger("cost_num");
            if (costNum > 0) {
                String costKey = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-chapter-unlock-cost");
                if (!redisCache.sIsMember(costKey, userBehaviorDTO.getUid())) {
                    staticsDO.setCostAccountNum(staticsDO.getCostAccountNum() + 1);
                }

            }
        }

        if (idEnum == EventIdEnum.READ_OTHER_OPTION_UNLOCK) {
            int costNum = jsonObject.getInteger("cost_num");
            staticsDO.setCost(staticsDO.getCost() + costNum);
        }

        if (idEnum == EventIdEnum.RECHARGE_SUCC) {
            String oid = jsonObject.getString("oid");
            staticsDO.setPayAmount(staticsDO.getPayAmount() + shopOrderDOMapper.selectByOid(oid).getPrice().intValue());
        }

        bookChapterStaticsDOMapper.updateByPrimaryKeySelective(staticsDO);
    }

    private void processBookOption(UserBehaviorDTO userBehaviorDTO) {
        log.info("start,processBookOption,eventId={}", userBehaviorDTO.getEventId());
        EventIdEnum idEnum = EventIdEnum.mustFind(userBehaviorDTO.getEventId());
        if (idEnum == null || !idEnum.ifProcessBookOption()) {
            return;
        }
        JSONObject jsonObject = JSON.parseObject(userBehaviorDTO.getEventData());

        Integer bookId = Integer.parseInt(jsonObject.getString("book_id"));
        Integer chapterIndex = Integer.parseInt(jsonObject.getString("chapter_index"));
        String frameIndexStr = jsonObject.getString("frame_index");
        Integer frameIndex = frameIndexStr != null ? Integer.parseInt(frameIndexStr) : 0;
        // init
        String day = userBehaviorDTO.getEventTime().split(" ")[0];
        BookOptionStaticsDOExample example = new BookOptionStaticsDOExample();
        Date dayDate = TimeUtils.parse(day, "yyyy-MM-dd");
        example.createCriteria().andDayEqualTo(dayDate).andChannelEqualTo(userBehaviorDTO.getAppChannel())
                .andGeoNameEqualTo(userBehaviorDTO.getGeoName()).andBookIdEqualTo(bookId)
                .andChapterIndexEqualTo(chapterIndex).andOptionIndexEqualTo(frameIndex);
        List<BookOptionStaticsDO> staticsDOS = bookOptionStaticsDOMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(staticsDOS)) {
            BookOptionStaticsDO staticsDO = new BookOptionStaticsDO();
            staticsDO.setDay(dayDate);
            staticsDO.setChannel(userBehaviorDTO.getAppChannel());
            staticsDO.setGeoName(userBehaviorDTO.getGeoName());
            staticsDO.setBookId(bookId);
            staticsDO.setBookTitle(bookDAOMapper.selectByPrimaryKey((long) bookId).getTitle());
            staticsDO.setChapterIndex(chapterIndex);
            staticsDO.setOptionIndex(frameIndex);
            bookOptionStaticsDOMapper.insertSelective(staticsDO);
        }

        BookOptionStaticsDO staticsDO = bookOptionStaticsDOMapper.selectByExample(example).get(0);

        if (idEnum == EventIdEnum.READ_VIEW_OPTION) {
            staticsDO.setEnterOptionNum(staticsDO.getEnterOptionNum() + 1);

            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-option-enter");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setEnterOptionAccountNum(staticsDO.getEnterOptionAccountNum() + 1);
            }
        }

        if (idEnum == EventIdEnum.READ_EXIT_OPTION) {
            String key = getRedisBookReadKey(day, staticsDO.getBookId(), "total-statics-read-option-exit");
            if (!redisCache.sIsMember(key, userBehaviorDTO.getUid())) {
                staticsDO.setExitAccountNum(staticsDO.getExitAccountNum() + 1);
            }
        }

        if (idEnum == EventIdEnum.RECHARGE_SUCC) {
            String oid = jsonObject.getString("oid");
            staticsDO.setCost(staticsDO.getCost() + shopOrderDOMapper.selectByOid(oid).getPrice().intValue());
        }

        if (idEnum == EventIdEnum.RECHARGE_CLICK_SELECT) {
            int optionIndex = Integer.parseInt(jsonObject.getString("option_index"));
            if (optionIndex == 1) {
                staticsDO.setOptionSelectNumA(staticsDO.getOptionSelectNumA() + 1);
            }
            if (optionIndex == 2) {
                staticsDO.setOptionSelectNumB(staticsDO.getOptionSelectNumB() + 1);
            }
            if (optionIndex == 3) {
                staticsDO.setOptionSelectNumC(staticsDO.getOptionSelectNumC() + 1);
            }
            if (optionIndex == 4) {
                staticsDO.setOptionSelectNumD(staticsDO.getOptionSelectNumD() + 1);
            }
        }
        bookOptionStaticsDOMapper.updateByPrimaryKeySelective(staticsDO);
    }
}
